home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / µSim 1.1 / source / Input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-25  |  14.5 KB  |  522 lines  |  [TEXT/CWIE]

  1. /*
  2. Copyright © 1993-1997 Fabrizio Oddone
  3. ••• ••• ••• ••• ••• ••• ••• ••• ••• •••
  4. This source code is distributed as freeware:
  5. you may copy, exchange, modify this code.
  6. You may include this code in any kind of application: freeware,
  7. shareware, or commercial, provided that full credits are given.
  8. You may not sell or distribute this code for profit.
  9. */
  10.  
  11.  
  12. #include    "UtilsSys7.h"
  13. #include    "CursorBalloon.h"
  14. #include    "ZoomCode.h"
  15.  
  16. #include    "Globals.h"
  17. #include    "Input.h"
  18. #include    "Main.h"
  19. #include    "SimUtils.h"
  20.  
  21. //#pragma segment Main
  22.  
  23. /*    kTextMargin is the number of pixels we leave blank at the edge of the window. */
  24. enum {
  25. kTextMargin = 2,
  26.  
  27. /*    kCrChar is used to match with a carriage return when calculating the
  28.     number of lines in the TextEdit record. */
  29. kCrChar = 13,
  30.  
  31. /*    kButtonScroll is how many pixels to scroll horizontally when the button part
  32.     of the horizontal scrollbar is pressed. */
  33. kButtonScroll = 4
  34. };
  35.     
  36. /* static routines */
  37. static void IOIdealSize(WindowPtr theWindow, Rect * const idealContentSize);
  38. static void GetLocalUpdateRgn(WindowPtr window, RgnHandle localRgn);
  39. static pascal void VActionProc(ControlHandle control, short part);
  40. static pascal void HActionProc(ControlHandle control, short part);
  41. static void DrawWindow(WindowPtr window);
  42. static void AdjustTE(void);
  43. static void AdjustHorz(ControlHandle control, TEHandle docTE);
  44. static void AdjustVert(ControlHandle control, TEHandle docTE);
  45. static void AdjustScrollSizes(WindowPtr window);
  46. static void AdjustScrollValues(void);
  47. static short LinesInTE(TEHandle theTE);
  48.  
  49.  
  50. void IOHome(void)
  51. {
  52. ControlHandle    vscrollBar = gIODoc.docVScroll;
  53.  
  54. SetControlValue(vscrollBar, GetControlMinimum(vscrollBar));
  55. AdjustTE();
  56. }
  57.  
  58. void IOEnd(void)
  59. {
  60. ControlHandle    vscrollBar = gIODoc.docVScroll;
  61.  
  62. SetControlValue(vscrollBar, GetControlMaximum(vscrollBar));
  63. AdjustTE();
  64. }
  65.  
  66. void IOPgUp(void)
  67. {
  68. VActionProc(gIODoc.docVScroll, kControlPageUpPart);
  69. }
  70.  
  71. void IOPgDn(void)
  72. {
  73. VActionProc(gIODoc.docVScroll, kControlPageDownPart);
  74. }
  75.  
  76. /*    Called when a mouseDown occurs in the grow box of an active window. In
  77.     order to eliminate any 'flicker', we want to invalidate only what is
  78.     necessary. Since ResizeWindow invalidates the whole portRect, we save
  79.     the old TE viewRect, intersect it with the new TE viewRect, and
  80.     remove the result from the update region. However, we must make sure
  81.     that any old update region that might have been around gets put back. */
  82.  
  83. void DoGrowWindow(WindowPtr window, EventRecord    *event)
  84. {
  85. Rect    tempRect;
  86. long    growResult;
  87. RgnHandle    tempRgn;
  88. DocumentIOPeek doc;
  89.  
  90. if (window == gWPtr_IO) {
  91.     tempRect.right = tempRect.bottom = 0x7FFF;        /* set up limiting values */
  92.     tempRect.top = tempRect.left = kMinDocDim;
  93. /* see if it really changed size */
  94.     if (growResult = GrowWindow(window, event->where, &tempRect)) {
  95.         doc = &gIODoc;
  96.         tempRect = (*doc->docTE)->viewRect;        /* save old text box */
  97.         tempRgn = NewRgn();
  98.         GetLocalUpdateRgn(window, tempRgn);        /* get localized update region */
  99.         SizeWindow(window, LoWrd(growResult), HiWrd(growResult), true);
  100.         ResizeWindow(window);
  101. /* calculate & validate the region that hasn’t changed so it won’t get redrawn */
  102.         SectRect(&tempRect, &(*doc->docTE)->viewRect, &tempRect);
  103.         ValidRect(&tempRect);                /* take it out of update */
  104.         InvalRgn(tempRgn);                    /* put back any prior update */
  105.         DisposeRgn(tempRgn);
  106.         }
  107.     }
  108. } /* DoGrowWindow */
  109.  
  110.  
  111. /*     Called when a mouseClick occurs in the zoom box of an active window. */
  112.  
  113. void DoZoomWindow(WindowPtr w, short code)
  114. {
  115. ZoomTheWindow((WindowPeek)w, code, IOIdealSize, nil);
  116. ResizeWindow(w);
  117. } /*  DoZoomWindow */
  118.  
  119.  
  120. // w is the current port
  121. void IOIdealSize(WindowPtr , Rect * const idealContentSize)
  122. {
  123. static const Rect    wideRect = {0, 0, 4000, 4000};
  124.  
  125. *idealContentSize = wideRect;
  126. }
  127.  
  128.  
  129. /* Called when the window has been resized to fix up the controls and content. */
  130.  
  131. void ResizeWindow(WindowPtr window)
  132. {
  133. InvalRect(&window->portRect);
  134. AdjustScrollbars(window, true);
  135. AdjustTE();
  136. } /* ResizeWindow */
  137.  
  138.  
  139. /* Returns the update region in local coordinates */
  140.  
  141. void GetLocalUpdateRgn(WindowPtr window, RgnHandle localRgn)
  142. {
  143. Point    mypt = { 0, 0};
  144.  
  145. LocalToGlobal(&mypt);
  146. CopyRgn(((WindowPeek) window)->updateRgn, localRgn);/* save old update region */
  147. OffsetRgn(localRgn, mypt.h, mypt.v);
  148. } /* GetLocalUpdateRgn */
  149.  
  150.  
  151. /*    This is called when an update event is received for a window.
  152.     It calls DrawWindow to draw the contents of an application window.
  153.     As an efficiency measure that does not have to be followed, it
  154.     calls the drawing routine only if the visRgn is non-empty. This
  155.     will handle situations where calculations for drawing or drawing
  156.     itself is very time-consuming. */
  157.  
  158. void DoUpdateWindow(WindowPtr window, short)
  159. {
  160. if (window == gWPtr_IO)
  161.     if (EmptyRgn(window->visRgn) == false)    /* draw if updating needs to be done */
  162.         DrawWindow(window);
  163. } /*DoUpdate*/
  164.  
  165.  
  166. /*    This is called when a window is activated or deactivated.
  167.     It calls TextEdit to deal with the selection. */
  168.  
  169. void DoActivateWindow(EventRecord */*evt*/, WindowPtr window, Handle, short, Boolean becomingActive)
  170. {
  171. Rect    growRect, tempRect;
  172. RgnHandle    tempRgn, clipRgn;
  173. DocumentIOPeek doc;
  174.  
  175. if (window == gWPtr_IO) {
  176.     doc = &gIODoc;
  177. /* the growbox needs to be redrawn on activation: */
  178.     growRect = window->portRect;
  179. /* adjust for the scrollbars */
  180.     growRect.top = growRect.bottom - kScrollbarAdjust + 1;
  181.     growRect.left = growRect.right - kScrollbarAdjust + 1;
  182.     if (becomingActive) {
  183. /*    since we don’t want TEActivate to draw a selection in an area where
  184.     we’re going to erase and redraw, we’ll clip out the update region
  185.     before calling it. */
  186.         tempRgn = NewRgn();
  187.         clipRgn = NewRgn();
  188.         GetLocalUpdateRgn(window, tempRgn);        /* get localized update region */
  189.         GetClip(clipRgn);
  190.         DiffRgn(clipRgn, tempRgn, tempRgn);        /* subtract updateRgn from clipRgn */
  191.         SetClip(tempRgn);
  192.         TEActivate(doc->docTE);
  193.         gTheInput = doc->docTE;
  194.         SetClip(clipRgn);                        /* restore the full-blown clipRgn */
  195.         DisposeRgn(tempRgn);
  196.         DisposeRgn(clipRgn);
  197.         InvalRect(&growRect);    /* we cannot avoid grow box flickering */
  198. /* the controls must be redrawn on activation: */
  199.         if ((*doc->docVScroll)->contrlVis == 0) {
  200.             ShowControl(doc->docVScroll);
  201.             tempRect = (*doc->docVScroll)->contrlRect;
  202.             ValidRect(&tempRect);
  203.             }
  204.         if ((*doc->docHScroll)->contrlVis == 0) {
  205.             ShowControl(doc->docHScroll);
  206.             tempRect = (*doc->docHScroll)->contrlRect;
  207.             ValidRect(&tempRect);
  208.             }
  209.         }
  210.     else {        
  211.         TEDeactivate(doc->docTE);
  212.         gTheInput = nil;
  213. /* the controls must be redrawn on deactivation: */
  214.         HideControl(doc->docVScroll);
  215.         HideControl(doc->docHScroll);
  216.         InvalRect(&growRect);
  217.         }
  218.     }
  219. } /*DoActivate*/
  220.  
  221.  
  222. /*    This is called when a mouseDown occurs in the content of a window. */
  223.  
  224. void DoContentClick(WindowPtr window, EventRecord *event)
  225. {
  226. Rect    teRect;
  227. Point    mouse;
  228. ControlHandle control;
  229. TEHandle    theTE;
  230. DocumentIOPeek doc;
  231. long    tempc;
  232. TEPtr    tPtr;
  233. short    part, value, lines;
  234.  
  235. if (window == gWPtr_IO) {
  236.     mouse = event->where;                /* get the click position */
  237.     GlobalToLocal(&mouse);
  238.     doc = &gIODoc;
  239. /* see if we are in the viewRect. if so, we won’t check the controls */
  240.     GetTERect(window, &teRect);
  241.     theTE = doc->docTE;
  242.     if (PtInRect(mouse, &teRect)) {
  243.         /* see if we need to extend the selection */
  244.         TEClick(mouse, (event->modifiers & shiftKey) != 0, theTE);
  245.         AdjustScrollValues();
  246.         }
  247.     else {
  248.         part = FindControl(mouse, window, &control);
  249.         switch ( part ) {
  250.             case 0:        /* do nothing for viewRect case */
  251.                 break;
  252.             case kControlIndicatorPart:
  253.                 value = GetControlValue(control);
  254.                 part = TrackControl(control, mouse, nil);
  255.                 if ( part ) {
  256.                     if ( control == doc->docVScroll ) {
  257.                         lines = LinesInTE(theTE);
  258.                         tPtr = *theTE;
  259.                         tempc = (lines * (long)tPtr->lineHeight) -
  260.                                 (tPtr->viewRect.bottom - tPtr->viewRect.top);
  261.                         TEPinScroll(0, tPtr->viewRect.top - tPtr->destRect.top -
  262.                             ((tempc * GetControlValue(control)) / GetControlMaximum(control)), theTE);
  263.                         }
  264.                     else
  265.                         TEPinScroll(value - GetControlValue(control), 0, theTE);
  266.                     }
  267.                 break;
  268.             default:        /* clicked in an arrow, so track & scroll */
  269.                 {
  270.                 ControlActionUPP HVActionProcUPP = NewControlActionProc(control == doc->docVScroll ? (ProcPtr)VActionProc : (ProcPtr)HActionProc);
  271.  
  272.                 (void)TrackControl(control, mouse, HVActionProcUPP);
  273.                 if (HVActionProcUPP)
  274.                     DisposeRoutineDescriptor(HVActionProcUPP);
  275.                 }
  276.                 break;
  277.             }
  278.         }
  279.     }
  280. } /*DoContentClick*/
  281.  
  282.  
  283. /* Slams the character typed in the TextEdit field, and
  284. activates memory-mapped Input when necessary */
  285.  
  286. void DoKeyDown(WindowPtr window, unsigned char key, Boolean isUserInput)
  287. {
  288. //if (window == gWPtr_IO) {
  289.     TEKey(key, gIODoc.docTE);
  290.     AdjustScrollbars(window, false);
  291.     if (isUserInput) {
  292.         gMMemory[kSIZE_RAM - 4] = 0;
  293.         gMMemory[kSIZE_RAM - 3] = key;
  294.         }
  295. //    }
  296. } /*DoKeyDown*/
  297.  
  298. /* Determines how much to change the value of the vertical scrollbar by and how
  299.     much to scroll the TE record. */
  300.  
  301. pascal void VActionProc(ControlHandle control, short part)
  302. {
  303. WindowPtr    window;
  304. TEPtr        te;
  305. short        amount;
  306.  
  307. if ( part ) {            /* if it was actually in the control */
  308.     window = (*control)->contrlOwner;
  309.     te = *gIODoc.docTE;
  310.     switch ( part ) {
  311.         case kControlUpButtonPart:
  312.             amount = te->lineHeight;
  313.             break;
  314.         case kControlDownButtonPart:
  315.             amount = - te->lineHeight;
  316.             break;
  317.         case kControlPageUpPart:
  318.             amount = te->viewRect.bottom - te->viewRect.top - te->lineHeight;
  319.             break;
  320.         case kControlPageDownPart:
  321.             amount = te->viewRect.top - te->viewRect.bottom + te->lineHeight;
  322.             break;
  323.         }
  324.     TEPinScroll(0, amount, gIODoc.docTE);
  325.     AdjustVert(control, gIODoc.docTE);
  326.     }
  327. } /* VActionProc */
  328.  
  329.  
  330. /* Determines how much to change the value of the horizontal scrollbar by and how
  331. much to scroll the TE record. */
  332.  
  333. pascal void HActionProc(ControlHandle control, short part)
  334. {
  335. register WindowPtr    window;
  336. register TEPtr        te;
  337. register short        amount;
  338.  
  339. if ( part ) {
  340.     window = (*control)->contrlOwner;
  341.     te = *gIODoc.docTE;
  342.     switch ( part ) {
  343.         case kControlUpButtonPart:
  344.             amount = kButtonScroll;
  345.             break;
  346.         case kControlDownButtonPart:
  347.             amount = - kButtonScroll;
  348.             break;
  349.         case kControlPageUpPart:
  350.             amount = te->viewRect.right - te->viewRect.left - kScrollbarAdjust;
  351.             break;
  352.         case kControlPageDownPart:
  353.             amount = te->viewRect.left - te->viewRect.right + kScrollbarAdjust;
  354.             break;
  355.         }
  356.     TEPinScroll(amount, 0, gIODoc.docTE);
  357.     AdjustHorz(control, gIODoc.docTE);
  358.     }
  359. } /* VActionProc */
  360.  
  361.  
  362. /* Draw the contents of an application window. */
  363.  
  364. void DrawWindow(WindowPtr window)
  365. {
  366. Rect    tempRect;
  367.  
  368. EraseRect(&window->portRect);
  369. tempRect = (*gIODoc.docTE)->viewRect;
  370. TEUpdate(&tempRect, gIODoc.docTE);
  371. DrawGrowIcon(window);
  372. UpdateControls(window, window->visRgn);
  373. } /*DrawWindow*/
  374.  
  375.  
  376. /* Return a rectangle that is inset from the portRect by the size of
  377.     the scrollbars and a little extra margin. */
  378.  
  379. void GetTERect(WindowPtr window, RectPtr teRect)
  380. {
  381. *teRect = window->portRect;
  382. teRect->left += kTextMargin;
  383. teRect->bottom -= kScrollbarAdjust;        /* and for the scrollbars */
  384. teRect->right -= kScrollbarAdjust;
  385. } /*GetTERect*/
  386.  
  387. /* Scroll the TERec around to match up to the potentially updated scrollbar
  388.     values. This is really useful when the window has been resized such that the
  389.     scrollbars became inactive but the TERec was already scrolled. */
  390.  
  391. void AdjustTE(void)
  392. {
  393. register TEPtr        te;
  394.  
  395. te = *gIODoc.docTE;
  396. TEPinScroll((te->viewRect.left - te->destRect.left) -
  397.         GetControlValue(gIODoc.docHScroll),
  398.         (te->viewRect.top - te->destRect.top) -
  399.             (GetControlValue(gIODoc.docVScroll) *
  400.             te->lineHeight),
  401.         gIODoc.docTE);
  402. } /*AdjustTE*/
  403.  
  404.  
  405. /* Calculate the new control maximum value and current value, whether it is the
  406. horizontal or vertical scrollbar. The vertical max is calculated by comparing the
  407. number of lines to the vertical size of the viewRect. The horizontal max is
  408. calculated by comparing the maximum document width to the width of the viewRect.
  409. The current values are set by comparing the offset between the view and
  410. destination rects. */
  411.  
  412. void AdjustHorz(ControlHandle control, TEHandle docTE)
  413. {
  414. TEPtr    te;
  415. short    max, min;
  416.  
  417. te = *docTE;
  418. max = (qd.screenBits.bounds.right - qd.screenBits.bounds.left) -
  419.             (te->viewRect.right - te->viewRect.left);
  420. if ( max < (min = GetControlMinimum(control)) )
  421.     max = min;
  422. SetControlMaximum(control, max);
  423. te = *docTE;    /* SetControlMaximum may move memory */
  424. SetControlValue(control, te->viewRect.left - te->destRect.left);
  425. } /*AdjustHorz*/
  426.  
  427. void AdjustVert(ControlHandle control, TEHandle docTE)
  428. {
  429. TEPtr    te;
  430. short    max, lines, min;
  431. long    divisor;
  432.  
  433. lines = LinesInTE(docTE);
  434. te = *docTE;
  435. max = lines - ((te->viewRect.bottom - te->viewRect.top) / te->lineHeight);
  436. if ( max < (min = GetControlMinimum(control)) ) max = min;
  437. SetControlMaximum(control, max);
  438. te = *docTE;    /* SetControlMaximum may move memory */
  439. divisor = (lines * (long)te->lineHeight) - (te->viewRect.bottom - te->viewRect.top) - (te->lineHeight >> 1);
  440. SetControlValue(control, divisor ?
  441.     (max * (long)(te->viewRect.top - te->destRect.top)) / divisor
  442.     : 0);
  443. } /*AdjustVert*/
  444.  
  445. /* Simply call the adjust routines for the vertical and horizontal scrollbars */
  446.  
  447. void AdjustScrollValues(void)
  448. {
  449. DocumentIOPeek doc;
  450.  
  451. doc = &gIODoc;
  452. AdjustHorz(doc->docHScroll, doc->docTE);
  453. AdjustVert(doc->docVScroll, doc->docTE);
  454. } /*AdjustScrollValues*/
  455.  
  456.  
  457. /* Re-calculate the position and size of the viewRect and the scrollbars */
  458.  
  459. void AdjustScrollSizes(WindowPtr window)
  460. {
  461. Rect        teRect;
  462. register DocumentIOPeek doc;
  463.  
  464. doc = &gIODoc;
  465. GetTERect(window, &teRect);            /* start with TERect */
  466. (*doc->docTE)->viewRect = teRect;
  467. SetupVertScrollBar(window, doc->docVScroll);
  468. SetupHorzScrollBar(window, doc->docHScroll);
  469. } /*AdjustScrollSizes*/
  470.  
  471. void AdjustScrollbars(WindowPtr window, Boolean needsResize)
  472. {
  473. Rect        tempRect;
  474.  
  475. if ( needsResize ) {        /* move & size as needed */
  476.     HideControl(gIODoc.docVScroll);
  477.     HideControl(gIODoc.docHScroll);
  478.     AdjustScrollSizes(window);
  479.     }
  480. AdjustScrollValues();    /* fool with max and current value */
  481. if ( needsResize ) {                        /* move & size as needed */
  482.     ShowControl(gIODoc.docVScroll);
  483.     ShowControl(gIODoc.docHScroll);
  484.     tempRect = (*gIODoc.docVScroll)->contrlRect;
  485.     ValidRect(&tempRect);
  486.     tempRect = (*gIODoc.docHScroll)->contrlRect;
  487.     ValidRect(&tempRect);
  488.     }
  489. } /* AdjustScrollbars */
  490.  
  491. /* LinesInTE: returns the number of lines in a TextEdit field;
  492. since it calls TEGetText, it _can_ move memory */
  493.  
  494. static short LinesInTE(TEHandle theTE)
  495. {
  496. register Handle    textHand;
  497. register short    lines;
  498.  
  499. lines = (*theTE)->nLines;
  500. textHand = (Handle)TEGetText(theTE);
  501. /* since nLines isn’t right if the last character is a return, check for that case */
  502. if ( *(*textHand + InlineGetHandleSize(textHand) - 1) == kCrChar )
  503.     lines++;
  504. return(lines);
  505. }
  506.  
  507. /* procedure called when closing the IO window */
  508.  
  509. void CloseIO(WindowPtr w)
  510. {
  511. DoCloseWindow(w, kMItem_IO);
  512. }
  513.  
  514. void RecalcIO(DialogRef w, RgnBalloonCursPtr theObj)
  515. {
  516. Rect    tempRect;
  517.  
  518. GetTERect(w, &tempRect);
  519. RectRgn(theObj->zoneLocal, &tempRect);
  520. }
  521.  
  522.